use std::io::Write;

use anyhow::Result;
use flate2::Compression;
use flate2::write::GzEncoder;
use nom::AsBytes;

use crate::{constants, handlers, http_headers::HttpHeader, http_request::HttpRequest, http_response::{HttpResponse, ResponseStatusLine}};
use crate::http_response::ResponseBody;

/// 路由实现，用于注册handler函数
pub fn route(http_request: HttpRequest) -> Result<HttpResponse> {
    let mut http_response = match http_request.request_line.uri {
        "/" => HttpResponse::new(ResponseStatusLine::success("OK")),
        "/user-agent" => handlers::handle_user_agent_request(&http_request),
        _ => {
            if http_request.request_line.uri.starts_with("/echo/") {
                //处理回响请求
                handlers::handle_echo_request(&http_request)
            } else if http_request.request_line.uri.starts_with("/files/") && http_request.request_line.method.to_uppercase().eq(constants::METHOD_GET) {
                //处理文件响应请求
                handlers::handle_get_file_request(&http_request)
            } else if http_request.request_line.uri.starts_with("/files/") && http_request.request_line.method.to_uppercase().eq(constants::METHOD_POST) {
                handlers::handle_post_file_request(&http_request)
            } else {
                HttpResponse::new(ResponseStatusLine::error(404, "Not Found"))
            }
        }
    };

    //检查是否包含Content-Encoding请求头
    let encoding_header = http_request.headers.iter().find(|h| constants::ACCEPT_ENCODING.eq_ignore_ascii_case(h.0));
    if let Some(h) = encoding_header {
        let supported_encoding_type: &'static str = get_supported_encoding_type(h.1.to_string());
        if !supported_encoding_type.is_empty() {
            // 如果是gzip则采用gzip的方式对body进行压缩
            if supported_encoding_type.eq_ignore_ascii_case(constants::GZIP_ENCODING) {
                let mut encoded_body = Vec::new();
                let mut encoder = GzEncoder::new(&mut encoded_body, Compression::default());
                if let Some(ref response_data) = http_response.body {
                    let _ =encoder.write_all(response_data.to_bytes_vec().as_bytes());
                }

                match encoder.finish() {
                    Ok(v) => {
                        http_response.add_header(HttpHeader::from_num(constants::CONTENT_LENGTH, v.len()));
                        http_response.add_header(HttpHeader::from_str(constants::CONTENT_ENCODING, constants::GZIP_ENCODING));
                        http_response.body = Some(ResponseBody::BytesBody(v.to_vec()));
                    },
                    Err(error) => {
                        eprint!("{}", error);
                    }
                }
            }
        }
    }
    
    Ok(http_response)
}

/// 检查编码类型是否被支持
fn get_supported_encoding_type(encoding_type: String) -> &'static str {
    if encoding_type.is_empty() {
        ""
    } else {
        let types = encoding_type.split(",").filter(|x| !x.is_empty()).map(|x| x.trim()).collect::<Vec<&str>>();
        match constants::SUPPORTED_ENCODING.iter().find(|x| types.contains(x)) {
            None => "",
            Some(v) => v
        }
    }
}